﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Markup;

namespace Red.Core
{
    /// <summary>
    ///     Responsible for mapping view control types to data template objects
    /// </summary>
    public static class DataControlTemplateMapper
    {
        private static Dictionary<Type, DataTemplate> templateMap = new Dictionary<Type, DataTemplate>();

        /// <summary>
        ///     Creates and caches DataTemplate objects for different control types
        /// </summary>
        /// <param name="controlType">View control type</param>
        /// <returns>Newly created or previously cached DataTemplate</returns>
        public static DataTemplate GetTemplateForControl( Type controlType )
        {
            DataTemplate result;
            if ( !templateMap.TryGetValue( controlType, out result ) )
            {
                result = CreateTemplate( controlType );
                templateMap.Add( controlType, result );
            }
            return result;
        }

        private static DataTemplate CreateTemplate( Type type )
        {
            // NOTE: Creating template by composing an xml looks hacky, but apparently is the only correct way (see http://goo.gl/D89bc9)
            const string xamlTemplate = @"<DataTemplate><v:{0}/></DataTemplate>";
            string xaml = String.Format( xamlTemplate, type.Name );

            var context = new ParserContext();
            context.XamlTypeMapper = new XamlTypeMapper( new string[0] );
            context.XamlTypeMapper.AddMappingProcessingInstruction( "v", type.Namespace, type.Assembly.FullName );
            context.XmlnsDictionary.Add( "", "http://schemas.microsoft.com/winfx/2006/xaml/presentation" );
            context.XmlnsDictionary.Add( "x", "http://schemas.microsoft.com/winfx/2006/xaml" );
            context.XmlnsDictionary.Add( "v", "v" );

            return (DataTemplate)XamlReader.Parse( xaml, context );
        }
    }
}
